/*
 * EscDialog.java - Handles ESCAPE key for you
 */
package org.lex.swing.widgets;

import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JDialog;

/**
 * A dialog box that handles window closing, and the ESCAPE key for you. All you
 * have to do is implement cancel(), which called when Escape is pressed, or
 * window is closing).
 */
public class EnhancedDialog extends JDialog {
	protected KeyHandler keyHandler;

	public EnhancedDialog() {
		this(null, null, false);
	}

	public EnhancedDialog(String title) {
		this(null, title, false);
	}

	public EnhancedDialog(Window parent) {
		this(parent, null, false);
	}

	public EnhancedDialog(Window parent, String title) {
		this(parent, title, false);
	}

	public EnhancedDialog(Window parent, String title, boolean modal) {
		super(parent, title);
		this.setModal(modal);
		this.initialize();
	}

	public void setDefaultButton(JButton defaultButton) {
		this.getRootPane().setDefaultButton(defaultButton);
	}

	public JButton getDefaultButton() {
		return this.getRootPane().getDefaultButton();
	}

	public void cancel() {
		this.dispose();
	}

	public void moveToParent() {
		this.setLocationRelativeTo(this.getParent());
	}

	private void initialize() {
		this.keyHandler = new KeyHandler();
		((Container) getLayeredPane()).addContainerListener(new ContainerHandler());
		this.getContentPane().addContainerListener(new ContainerHandler());
		this.addKeyListener(keyHandler);
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				cancel();
			}
		});
	}

	// Recursively adds our key listener to sub-components
	class ContainerHandler extends ContainerAdapter {
		public void componentAdded(ContainerEvent evt) {
			componentAdded(evt.getChild());
		}

		public void componentRemoved(ContainerEvent evt) {
			componentRemoved(evt.getChild());
		}

		private void componentAdded(Component comp) {
			comp.addKeyListener(keyHandler);
			if (comp instanceof Container) {
				Container cont = (Container) comp;
				cont.addContainerListener(this);
				Component[] comps = cont.getComponents();
				for (int i = 0; i < comps.length; i++) {
					componentAdded(comps[i]);
				}
			}
		}

		private void componentRemoved(Component comp) {
			comp.removeKeyListener(keyHandler);
			if (comp instanceof Container) {
				Container cont = (Container) comp;
				cont.removeContainerListener(this);
				Component[] comps = cont.getComponents();
				for (int i = 0; i < comps.length; i++) {
					componentRemoved(comps[i]);
				}
			}
		}
	}

	class KeyHandler extends KeyAdapter {
		public void keyPressed(KeyEvent evt) {
			if (evt.isConsumed())
				return;
			if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
				cancel();
				evt.consume();
			}
		}
	}
}
